package org.example.com.editor.editor;

import lombok.Getter;
import org.example.com.editor.command.commandHistory.CommandHistoryItem;

import java.util.*;

@Getter
public class TextEditor implements Editor {
    private final String filePath;
    private final List<String> content;
    private boolean modified;
    private final Deque<CommandHistoryItem> undoStack = new ArrayDeque<>();
    private CommandHistoryItem redoCommand; // 仅存储上次 undo 的命令（支持一次重做）

    public TextEditor(String filePath, List<String> content, boolean modified) {
        this.filePath = filePath;
        this.content = new ArrayList<>(content != null ? content : Collections.emptyList());
        this.modified = modified;
    }

    /**
     * 记录新命令：清空 redoCommand（新操作覆盖上次 undo 的重做机会）
     */
    public void recordCommand(CommandHistoryItem command) {
        if (command != null) {
            redoCommand = null; // 新命令执行后，无法再重做之前的 undo 操作
            undoStack.push(command);
        }
    }

    /**
     * undo：从 undoStack 弹出 → 存入 redoCommand（支持一次重做）
     */
    public CommandHistoryItem undo() {
        if (undoStack.isEmpty()) {
            throw new IllegalStateException("没有可撤销的操作");
        }
        CommandHistoryItem command = undoStack.pop();
        redoCommand = command; // 仅保存上次 undo 的命令
        return command;
    }

    /**
     * redo：仅重做上次 undo 的命令 → 执行后压回 undoStack → 清空 redoCommand（确保只能重做一次）
     */
    public CommandHistoryItem redo() {
        if (redoCommand == null) {
            throw new IllegalStateException("没有可重做的操作");
        }
        CommandHistoryItem command = redoCommand;
        // 关键：redo 后将命令重新压回 undoStack，支持再次 undo
        undoStack.push(command);
        redoCommand = null; // 清空，确保只能重做一次
        return command;
    }
    // ==================== 基础原子操作 ====================
    private void baseInsert(int lineNum, int colNum, String text) {
        List<String> lines = this.content;
        int originalLineIndex = lineNum - 1;

        while (lines.size() < originalLineIndex) {
            lines.add("");
        }

        String[] splitText = text.split("\\\\n", -1);
        if (splitText.length == 0) return;

        String originalLine = originalLineIndex < lines.size() ? lines.get(originalLineIndex) : "";
        int colIndex = colNum - 1;

        if (colIndex > originalLine.length()) {
            originalLine = String.format("%-" + colIndex + "s", originalLine);
        }

        String prefix = originalLine.substring(0, Math.min(colIndex, originalLine.length()));
        String suffix = originalLine.substring(Math.min(colIndex, originalLine.length()));

        if (splitText.length == 1) {
            String newLine = prefix + splitText[0] + suffix;
            if (originalLineIndex < lines.size()) {
                lines.set(originalLineIndex, newLine);
            } else {
                lines.add(newLine);
            }
        } else {
            splitText[splitText.length - 1] += suffix;
            String newFirstLine = prefix + splitText[0];
            if (originalLineIndex < lines.size()) {
                lines.set(originalLineIndex, newFirstLine);
            } else {
                lines.add(newFirstLine);
            }
            for (int i = 1; i < splitText.length; i++) {
                lines.add(originalLineIndex + i, splitText[i]);
            }
        }

        this.modified = true;
    }

    private String baseDelete(int lineNum, int colNum, int length) {
        List<String> lines = this.content;
        int lineIndex = lineNum - 1;

        if (lineIndex >= lines.size()) {
            return null;
        }

        String targetLine = lines.get(lineIndex);
        int startIndex = colNum - 1;

        if (startIndex >= targetLine.length()) {
            return null;
        }

        int endIndex = Math.min(startIndex + length, targetLine.length());
        String newLine = targetLine.substring(0, startIndex) + targetLine.substring(endIndex);
        if (newLine.isEmpty()) {
            lines.remove(lineIndex);
        } else {
            lines.set(lineIndex, newLine);
        }
        this.modified = true;
        return targetLine.substring(startIndex, endIndex);
    }

    // ==================== 公共API方法 ====================
    public void append(String text) {
        if (text == null || text.isEmpty()) {
            throw new IllegalArgumentException("追加的文本不能为空！");
        }

        int lineNum = content.isEmpty() ? 1 : content.size() + 1;
        int colNum = 1;

        baseInsert(lineNum, colNum, text);
    }

    public void insert(int lineNum, int colNum, String text) {
        validatePosition(lineNum, colNum, true);
        baseInsert(lineNum, colNum, text);
    }

    public String delete(int lineNum, int colNum, int length) {
        validatePosition(lineNum, colNum, false);
        validateDeleteLength(lineNum, colNum, length);
        return baseDelete(lineNum, colNum, length);
    }

    public String replace(int lineNum, int colNum, int length, String newText) {
        validatePosition(lineNum, colNum, false);
        validateDeleteLength(lineNum, colNum, length);

        String deletedText = baseDelete(lineNum, colNum, length);
        baseInsert(lineNum, colNum, newText);
        return deletedText;
    }

    // ==================== 撤销操作 ====================
    public void undoAppend(String appendedText) {
        String[] lines = appendedText.split("\\\\n", -1);
        int totalLines = lines.length;

        if (totalLines == 0) return;

        if (totalLines == 1) {
            int lastLineIndex = content.size() - 1;
            if (lastLineIndex >= 0) {
                String lastLine = content.get(lastLineIndex);
                int charsToRemove = appendedText.length();
                int startCol = Math.max(1, lastLine.length() - charsToRemove + 1);
                baseDelete(content.size(), startCol, charsToRemove);
            }
        } else {
            for (int i = 0; i < totalLines; i++) {
                if (!content.isEmpty()) {
                    content.remove(content.size() - 1);
                }
            }
        }
        this.modified = true;
    }

    public void undoInsert(int lineNum, int colNum, String insertedText) {
        String[] splitText = insertedText.split("\\\\n", -1);
        int insertLineCount = splitText.length;

        if (insertLineCount == 1) {
            int charsToRemove = insertedText.length();
            baseDelete(lineNum, colNum, charsToRemove);
        } else {
            int lastInsertedLineNum = lineNum + insertLineCount - 1;
            String lastInsertedLineContent = "";

            if (lastInsertedLineNum <= content.size()) {
                lastInsertedLineContent = content.get(lastInsertedLineNum - 1);
            }

            for (int i = insertLineCount - 1; i > 0; i--) {
                int lineToRemove = lineNum + i;
                if (lineToRemove <= content.size()) {
                    content.remove(lineToRemove - 1);
                }
            }

            if (lineNum <= content.size()) {
                String firstLineContent = content.get(lineNum - 1);
                String prefix = firstLineContent.substring(0, Math.max(0, firstLineContent.length() - splitText[0].length()));
                String suffix = "";
                if (splitText.length > 0 && lastInsertedLineContent.length() >= splitText[splitText.length - 1].length()) {
                    suffix = lastInsertedLineContent.substring(splitText[splitText.length - 1].length());
                }
                String originalLine = prefix + suffix;
                if (originalLine.isEmpty()) {
                    content.remove(lineNum - 1);
                } else {
                    content.set(lineNum - 1, originalLine);
                }
            }
        }

        this.modified = true;
    }

    /**
     * 撤销删除：通过原行长度精准判断整行删除
     */
    public void undoDelete(int lineNum, int colNum, String deletedText, int originalLineLength) {
        // 精准判断：整行删除 = 从行首开始（colNum=1）+ 删除内容长度 == 原行长度
        boolean isFullLineDelete = (colNum == 1 && deletedText.length() == originalLineLength);

        if (isFullLineDelete && lineNum <= content.size()) {
            // 整行删除：插入新行恢复
            content.add(lineNum - 1, deletedText);
        } else {
            // 部分删除：在当前行插入文本恢复
            baseInsert(lineNum, colNum, deletedText);
        }
        this.modified = true;
    }

    /**
     * 撤销替换：通过原行长度精准判断行合并
     */
    public void undoReplace(int lineNum, int colNum, String originalText, String newText, int originalLineLength) {
        // 精准判断：行合并 = 从行首开始（colNum=1）+ 原文本长度 == 原行长度（整行删除）+ 当前行以newText开头
        boolean isLineMerged = false;
        if (lineNum <= content.size() && colNum == 1 && originalText.length() == originalLineLength) {
            String currentLine = content.get(lineNum - 1);
            isLineMerged = currentLine.startsWith(newText);
        }

        if (isLineMerged) {
            // 行合并场景：拆分并恢复行结构
            String currentLine = content.get(lineNum - 1);
            String restoredNextLine = currentLine.substring(newText.length());
            content.set(lineNum - 1, restoredNextLine);
            content.add(lineNum - 1, originalText);
        } else {
            // 普通替换场景：删除新文本 + 插入原文本
            baseDelete(lineNum, colNum, newText.length());
            baseInsert(lineNum, colNum, originalText);
        }
        this.modified = true;
    }

    // ==================== 辅助方法 ====================
    private void validatePosition(int lineNum, int colNum, boolean allowEndPosition) {
        if (lineNum < 1) {
            throw new IllegalArgumentException("行号不能小于1");
        }

        if (content.isEmpty()) {
            if (lineNum != 1 || colNum != 1) {
                throw new IllegalArgumentException("空文件只能在1:1位置操作");
            }
            return;
        }

        if (lineNum > content.size()) {
            throw new IllegalArgumentException("行号越界！当前文件总行数为" + content.size() + "，行号范围：1 ~ " + content.size());
        }

        String targetLine = content.get(lineNum - 1);
        int maxCol = allowEndPosition ? targetLine.length() + 1 : targetLine.length();

        if (colNum < 1 || colNum > maxCol) {
            throw new IllegalArgumentException("列号越界！当前行长度为" + targetLine.length() +
                    "，列号范围：1 ~ " + maxCol);
        }
    }

    private void validateDeleteLength(int lineNum, int colNum, int length) {
        if (length < 1) {
            throw new IllegalArgumentException("删除长度必须大于0");
        }

        String targetLine = content.get(lineNum - 1);
        int remainingChars = targetLine.length() - (colNum - 1);

        if (length > remainingChars) {
            throw new IllegalArgumentException("删除长度超出行尾");
        }
    }

    private String getTextAt(int lineNum, int colNum, int length) {
        String targetLine = content.get(lineNum - 1);
        int startIndex = colNum - 1;
        int endIndex = Math.min(startIndex + length, targetLine.length());
        return targetLine.substring(startIndex, endIndex);
    }

    @Override
    public void setModified(boolean modified) {
        this.modified = modified;
    }
}